grammar LocData;

@header {
	package data.grammar;
	
	import data.*;
	import stream.DebugStream;
	import java.util.Stack;
}

@members {
	private DebugStream db;
	private Group group;
	
	private Stack<String> errorContextStack;
	
	public LocDataParser(TokenStream in, DebugStream db, Group group) {
		this(in);
		this.db = db;
		this.group = group;
		this.errorContextStack = new Stack<String>();
	}
	
	@Override
	public String getErrorMessage(RecognitionException e, String[] tokenNames) {
		if (errorContextStack.isEmpty()) {
			return super.getErrorMessage(e, tokenNames) + " (" + group + ")";
		}
		return super.getErrorMessage(e, tokenNames) + " in " + errorContextStack.peek() + " (" + group + ")";
	}
}

INT :	'0'..'9'+
    ;

WS  :   ' ' {$channel=HIDDEN;}
    ;
    
COMMENT
    :   '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}
    ;
    
ENDLINE
	:	'\r'? '\n'
	;
	
TAB	:	'\t'
	;

start
	:	(slide (ENDLINE slide)*)?
		ENDLINE? EOF
	;
	
slide
scope{Slide curSlide;}
@init { errorContextStack.push("slide definition"); }
@after{ errorContextStack.pop(); }
	:	INT 
		{	$slide::curSlide = new Slide(Integer.parseInt($INT.getText())); 
			group.addSlide($slide::curSlide);
		} 
		data?
	;
	
data:	TAB cell (ENDLINE TAB cell)*
	;
	
cell
scope{Cell curCell;}
@init{
	$cell::curCell = new Cell($slide::curSlide);
	$slide::curSlide.addCell($cell::curCell);
	
	errorContextStack.push("cell definition");
}
@after { errorContextStack.pop(); }
	:	cyto? TAB mem?
	;
	
cyto:	cytoCluster (('+'|',') cytoCluster)*
	;
	
mem	:	memCluster (('+'|',') memCluster)*
	;
	
cytoCluster
@init { errorContextStack.push("cytoplasmic cluster data"); }
@after { errorContextStack.pop(); }
	:	INT
		{
			Cluster cluster = new Cluster($cell::curCell, Integer.parseInt($INT.getText()), false);
			$cell::curCell.addCluster(cluster);
		}
	;
	
memCluster
@init { errorContextStack.push("membrane cluster data"); }
@after { errorContextStack.pop(); }
	:	INT
		{
			Cluster cluster = new Cluster($cell::curCell, Integer.parseInt($INT.getText()), true);
			$cell::curCell.addCluster(cluster);
		}
	;